// ----------------------------------------------------------------------------
// thread.h
// ----------------------------------------------------------------------------
/*
 Description:
 基本スレッドクラス.

 ----------------------------------------------------------------
 使い方.

 1. 任意の位置で、Threadクラスのインスタンスを作成する.
	Thread reader;
 
 2. Initializeメソッドを呼び出して、スレッドを機能させる.
    reader.Initialize("reader-thread", readerFunction, argument, [AffinityMask], [Priority], [StackSize]);
	第一引数 : スレッド名.
	第二引数 : スレッドを実行する関数へのポインタ.
	第三引数 : スレッド引数(void型へのポインタ)
	第四引数 : アフィニティーマスク.            [指定しない場合、AFINITY_ALL]
	第五引数 : プライオリティ値.               [指定しない場合、PRIO_NORMAL]
	第六引数 : スレッドに割り当てるスタックサイズ.[指定しない場合、kDefaultThreadStackSize(64Kbytes)]
 
 3. Joinメソッドを呼び出すことでスレッド終了を待つ.
     reader.Join();
 
 */
#pragma once
#include <fw/base/core/assertion.h>
#include <fw/base/core/noncopyable.h>

namespace fw
{
    typedef void* ThreadArg;
	
    typedef void (*ThreadFunc)(ThreadArg);
	
    class ThreadImpl;
	
	class Thread : private ::fw::NonCopyable
	{
	public:

		enum Priority
		{
			PRIO_LOWEST = 0,
			PRIO_LOW,
			PRIO_NORMAL,
			PRIO_HIGH,
			PRIO_HIGHEST,
		}; // enum Priority 

		enum Affinity
		{
			AFFINITY_CORE0 = 0x01,
			AFFINITY_CORE1 = 0x02,
			AFFINITY_CORE2 = 0x04,
			AFFINITY_CORE3 = 0x08,
			AFFINITY_CORE4 = 0x10,
			AFFINITY_CORE5 = 0x20,
			AFFINITY_CORE6 = 0x40,
			AFFINITY_CORE7 = 0x80,
			
			AFFINITY_ALL   = (AFFINITY_CORE0|AFFINITY_CORE1|AFFINITY_CORE2|AFFINITY_CORE3
							 |AFFINITY_CORE4|AFFINITY_CORE5|AFFINITY_CORE6|AFFINITY_CORE7),
		}; // enum Affinity 
		
		static const size_t kDefaultThreadStackSize = (64*1024);
		
		 Thread();
		
		~Thread();
		
		void					Attach		(const char* name, Affinity affinitymask=AFFINITY_ALL);

		void					Initialize	(const char*  name,
											 ThreadFunc   func,
											 ThreadArg    arg,
											 Affinity     affinitymask=AFFINITY_ALL,
											 Priority     priority=PRIO_NORMAL,
											 size_t       stacksize=kDefaultThreadStackSize);
		
		void					Join		();

		static void				Sleep		(int msec);
		
		static void				Yield		();
		
		static int				GetNumberOfProcessors();
		
	private:
		
		ThreadImpl*				m_impl;
		
	}; // class Thread 
	
} // namespace fw 
